package com.xxd.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.xxd.rpt3.Entity.JwtTokenHis;
import com.xxd.rpt3.Entity.User;
import com.xxd.rpt3.repository.JwtTokenHisRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;

/**
 * @Author XuXd
 * @Description: token 工具类
 * @CreateDate: 11:19 2019-09-17
 * @Modified by: *
 */
@Component
public class JwtUtil {

	public static final String USER_CODE = "user_code";
	public static final String USER_NAME = "user_name";
	public static final String TOKEN_NAME = "token";
	// 默认30分钟失效
	public static int DEFAULT_TIME = 1800000;

	private String tokenId;
	private String token;
	private int keepDay;


    public JwtUtil() {
        this.token = tokenId;
        this.tokenId = token;
        this.keepDay = 0;
    }
	public JwtUtil(String tokenId, String token) {
		this.token = tokenId;
		this.tokenId = token;
		this.keepDay = 0;
	}

	public JwtUtil(User user) {
		this.token = JwtUtil.sign(user.getCode(), user.getSalt());
		this.tokenId = JwtUtil.newTokenId();
		this.keepDay = 0;
	}

	public JwtUtil(User user,int keepDay) {
		long keepTime = DEFAULT_TIME;
		if(keepDay == 0 ){

		}else if(keepDay >= 1){
			keepTime = 24*60*60*1000 * keepDay;
		}else if(keepDay == -1){
			keepTime = -1;
		}
		this.token = JwtUtil.sign(user.getCode(), user.getSalt(),keepTime);
		this.tokenId = JwtUtil.newTokenId();
		this.keepDay = keepDay;
	}

	public int getKeepDay() {
		return keepDay;
	}

	public void setKeepDay(int keepDay) {
		this.keepDay = keepDay;
	}

	public String getTokenId() {
		return tokenId;
	}

	public void setTokenId(String tokenId) {
		this.tokenId = tokenId;
	}

	public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	/**
	 * 获取签发时间
	 * 
	 * @param token
	 * @return
	 */
	public static Date getIssuedAtDate(String token) {
		try {
			DecodedJWT jwt = JWT.decode(token);
			return jwt.getIssuedAt();
		} catch (Exception e) {
			return null;
		}
	}

	public static long getIssuedAtLong(String token) {
		try {
			return getIssuedAtDate(token).getTime();
		} catch (Exception e) {
			return 0;
		}
	}
	/**
	 * 获取用户名ID
	 * 
	 * @param token
	 * @return
	 */
	public static String getUserName(String token) {
		try {
			DecodedJWT jwt = JWT.decode(token);
			return jwt.getClaim(USER_CODE).asString();
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 签名 token
	 * 
	 * @param username
	 * @param salt
	 * @param time
	 *            有效时长 单位：秒 second
	 * @return
	 */
	public static String sign(String username, String salt, long time) {
		try {
			// -1表示永不过期，默认100年有效期
			long newTime = (time >= 0 ? time : 365 * 50 * 24 * 60 * 60* 1000) ;
			Date date = new Date(System.currentTimeMillis() + newTime);
			// println( "${new Date()} ${date} ::::${newTime}")
			Algorithm algorithm = Algorithm.HMAC256(salt);
			// 附带username信息
			return JWT.create().withClaim(USER_CODE, username).withExpiresAt(date).withIssuedAt(new Date()).sign(algorithm);
		} catch (Exception e) {
			return null;
		}
	}

	public static String sign(String username, String salt) {
	    //System.out.println(DEFAULT_TIME);
		return sign(username, salt, DEFAULT_TIME);
	}

	/**
	 * token是否过期
	 * 
	 * @return true：过期
	 */
	public static boolean isExpired(String token) {
		Date now = Calendar.getInstance().getTime();
		DecodedJWT jwt = JWT.decode(token);
		return jwt.getExpiresAt().before(now);
	}

	/**
	 * 校验token
	 * 
	 * @param token
	 * @return
	 */
	public static boolean verify(String token, String user, String salt) {
		try {
			Algorithm algorithm = Algorithm.HMAC256(salt);
			JWTVerifier verifier = JWT.require(algorithm).withClaim(USER_CODE, user).build();
			verifier.verify(token);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public static String newTokenId() {
		return java.util.UUID.randomUUID().toString().replace("-", "");
	}

	/**
	 *@author: xuxd
	 *@description: **
	 *@params: ***
	 */

	public static void freshToken(JwtTokenHis jwtTokenHis, JwtTokenHisRepository jwtTokenHisRepository){
		//0、-1才会刷新token，其它数字不刷新
		if(jwtTokenHis.getKeepDay()>=1){
			return;
		}
		//定制刷新token策略:10分钟刷一次,当前请求时间，大于token签发时间10分以上则刷新
		//刷新his表、缓存
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				long signDate = JwtUtil.getIssuedAtLong(jwtTokenHis.getValue());
				long nowDate  = System.currentTimeMillis();
				//1000*60*10
				if(nowDate - signDate >= 1000*60*10){
					long verifyTime = (jwtTokenHis.getKeepDay()==-1)?-1:JwtUtil.DEFAULT_TIME;
					String newToken =  JwtUtil.sign(jwtTokenHis.getUserCode(),jwtTokenHis.getSalt(),verifyTime);
					EHCacheUtils.setTokenCache(jwtTokenHis.getKey(),jwtTokenHis);
					jwtTokenHis.setValue(newToken);
					jwtTokenHis.setSalt(jwtTokenHis.getSalt());
					jwtTokenHisRepository.save(jwtTokenHis);
				}
			}
		});
		thread.start();
	}


	public static void main(String[] args) {
		System.out.println(JwtUtil.sign("xxd", "xxd", -1));

		DecodedJWT jwt = JWT.decode(" eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2NvZGUiOiJzaGFyZS02NDE5MCIsImV4cCI6MTU2OTE3MTA2OCwiaWF0IjoxNTY5MDg0NjY4fQ.XeEAdfwpPTT4G1x2r_rCSq07SmDq9ZmWQ3NajH-s7kI");
		System.out.println(jwt.getIssuedAt());
		System.out.println(jwt.getExpiresAt());
		System.out.println(JwtUtil.verify(
				"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2NvZGUiOiJ4eGQiLCJleHAiOjMxNDU2ODU3MDgsImlhdCI6MTU2ODg4NTcwOH0.OWMxzPGLnb4uN9lsCE0iouq4FbroPphEEtCWozny6Uk", "xxd",
				"xxd"));
	}
}
